namespace Ex
{
    using System.Collections;
    using KeraLua;

    public class ExtensionMain
    {
        private readonly Lua lua;

        private readonly Hashtable env_container;

        public ExtensionMain()
        {
            lua = new();
            env_container = new()
            {
                ["main"] = new EnvLua(lua)
            };
        }

        public void CreateEnvironment(string env_name, Func<Lua, EnvLua> provider)
        {
            env_container[env_name] = provider(lua);
        }

        public void Do(Action<EnvLua> fun, string env_name = "main")
        {
            if (!env_container.ContainsKey(env_name))
            {
                throw new InvalidOperationException(string.Format("Lua environment {0} not found", env_name));
            }
            EnvLua env = (EnvLua)env_container[env_name]!;
            try
            {
                fun(env);
            }
            catch (LuaException)
            {
                foreach (var err in env.GetStackInfo()) { Console.Error.Write(err); }
            }
            finally
            {
            }
        }

        public T? Do<T>(Func<EnvLua, T> fun, string env_name = "main") where T : class
        {
            if (!env_container.ContainsKey(env_name))
            {
                throw new InvalidOperationException(string.Format("Lua environment {0} not found", env_name));
            }
            EnvLua env = (EnvLua)env_container[env_name]!;
            try
            {
                return fun(env);
            }
            catch (LuaException)
            {
                foreach (var err in env.GetStackInfo()) { Console.Error.Write(err); }
                return null;
            }
            finally
            {
            }
        }

        public void RunFile(string fileName, string env_name = "main")
        {
            if (!env_container.ContainsKey(env_name))
            {
                throw new InvalidOperationException(string.Format("Lua environment not found"));
            }
            EnvLua env = (EnvLua)env_container[env_name]!;
            try
            {
                env.RunFile(fileName);
            }
            catch (LuaException)
            {
                foreach (var err in env.GetStackInfo()) { Console.Error.Write(err); }
            }
            finally
            {
            }
        }
    }
}